<template>

  <el-container>
    <!-- 左侧 -->
    <!-- :width="isCollapse ? '64px' : '200px'"  根据菜单是否折叠，来选择左侧的宽度 -->
    <el-aside :width="isCollapse ? '64px' : '200px'">

      <el-button class="menuTitle" @click="home()">动力云客管理系统</el-button>

      <!--
        text-color="#fff"                    菜单栏字体颜色
        background-color="#334157"           菜单栏背景色
        active-text-color="#ffd04b"          当前激活菜单的字体颜色
        style="border-right: solid 0px;"     菜单栏的右边框设置为实线，厚度0px（保持对齐，没有凹陷）
        :default-active="currentRouterPath"  默认展开激活当前菜单，绑定变量，当前访问的路由路径
        :unique-opened="true"                只能同时展开一个子菜单
        :collapse="isCollapse"               菜单栏左右折叠展开，true是折叠，false是展开
        :collapse-transition="false"         关闭折叠展开动画
        :router="true"                       开启路由模式，以index作为path进行路由跳转
      -->
      <el-menu
          text-color="#fff"
          background-color="#334157"
          active-text-color="#ffd04b"
          style="border-right: solid 0px;"
          :default-active="currentRouterPath"
          :unique-opened="true"
          :collapse="isCollapse"
          :collapse-transition="false"
          :router="true">

        <el-sub-menu :index="index.toString()" v-for="(menuPermission, index) in this.user.menuPermissionList" :key="menuPermission.id">
          <template #title>
            <!-- 动态图标使用component -->
            <el-icon><component :is="menuPermission.icon" /></el-icon>
            <span>{{ menuPermission.name }}</span>
          </template>

          <el-menu-item :index="subMenuPermission.url" v-for="subMenuPermission in menuPermission.subMenuPermissionList" :key="subMenuPermission.id">
            <el-icon><component :is="subMenuPermission.icon" /></el-icon>
            {{ subMenuPermission.name }}
          </el-menu-item>
        </el-sub-menu>

        <!-- 注意：下面这个菜单仅作参考，不渲染到页面（v-if="false"）  -->
        <!-- 一级菜单（一级菜单的index属性值作为菜单的唯一标识） -->
        <el-sub-menu index="1" v-if="false">
          <!-- 一级菜单的图标和名字 -->
          <template #title>
            <!-- 图标（需要在main.js文件中注册） -->
            <el-icon><OfficeBuilding /></el-icon>
            <!-- 菜单名称 -->
            <span>市场活动</span>
          </template>
          <!-- 二级菜单（二级菜单的index属性值作为路由跳转） -->
          <el-menu-item index="/dashboard/activity">
            <el-icon><Management /></el-icon>
            市场活动
          </el-menu-item>
        </el-sub-menu>

      </el-menu>
    </el-aside>

    <!-- 右侧 -->
    <el-container class="rightContent">
      <!-- 右侧：上（头部） -->
      <el-header>
        <!-- 鼠标单击事件：左右展开和折叠左侧菜单栏 -->
        <el-icon class="show" @click="showMenu"><Fold /></el-icon>
        <!-- 用户信息下拉菜单 -->
        <el-dropdown :hide-on-click="false">
          <span class="el-dropdown-link">
            {{ user.name }}
            <el-icon class="el-icon--right"><arrow-down /></el-icon>
          </span>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item @click="myInfo()">我的资料</el-dropdown-item>
              <el-dropdown-item @click="changePwd()">修改密码</el-dropdown-item>
              <el-dropdown-item divided @click="logout()">退出登录</el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </el-header>

      <!-- 右侧：中（主体） -->
      <el-main>
        <!-- 渲染路由地址所对应的页面组件 -->
        <!-- v-if="isRouterAlive"  当isRouterAlive的值为true的时候展示路由组件，为false的时候隐藏 -->
        <router-view v-if="isRouterAlive"/>
      </el-main>

      <!-- 右侧：下（底部） -->
      <el-footer>
        © 2024
      </el-footer>
    </el-container>
  </el-container>

  <!-- 我的资料（对话框） -->
  <!--
    v-model                值为true时，显示对话框，false隐藏对话框
    center                 内容居中
    draggable              可拖拽的对话框
    :close-on-click-modal  是否可以通过点击对话框外的页面关闭对话框
    :destroy-on-close      对话框关闭时，是否销毁其中元素（例如：验证规则的提示信息）
  -->
  <el-dialog
      v-model="myInfoDialogVisible"
      title="我的资料"
      width="55%"  center  draggable
      :close-on-click-modal="false"
      :destroy-on-close="true">

    <!-- label-width="60px" 表单整体距离左侧的宽度（可以让表单内容排列整齐） -->
    <el-form label-width="100px">
      <!-- id -->
      <el-form-item label="ID">
        <div class="detail">&nbsp; {{ this.user.id }}</div>
      </el-form-item>

      <!-- 账号 -->
      <el-form-item label="账号">
        <div class="detail">&nbsp; {{ this.user.loginAct }}</div>
      </el-form-item>

      <!-- 姓名 -->
      <el-form-item label="姓名">
        <div class="detail">&nbsp; {{ this.user.name }}</div>
      </el-form-item>

      <!-- 手机 -->
      <el-form-item label="手机">
        <div class="detail">&nbsp; {{ this.user.phone }}</div>
      </el-form-item>

      <!-- 邮箱 -->
      <el-form-item label="邮箱">
        <div class="detail">&nbsp; {{ this.user.email }}</div>
      </el-form-item>

      <!-- 最后登录时间 -->
      <el-form-item label="最后登录时间">
        <div class="detail">&nbsp; {{ this.user.lastLoginTime }}</div>
      </el-form-item>
    </el-form>

    <template #footer>
      <el-button type="primary" plain @click="this.myInfoDialogVisible = false">关闭</el-button>
    </template>
  </el-dialog>

  <!-- 修改密码（对话框） -->
  <!--
    v-model                值为true时，显示对话框，false隐藏对话框
    center                 内容居中
    draggable              可拖拽的对话框
    :close-on-click-modal  是否可以通过点击对话框外的页面关闭对话框
    :destroy-on-close      对话框关闭时，是否销毁其中元素（例如：验证规则的提示信息）
  -->
  <el-dialog
      v-model="changePwdDialogVisible"
      title="修改密码"
      width="55%"  center  draggable
      :close-on-click-modal="false"
      :destroy-on-close="true">

    <!-- label-width="80px" 表单整体距离左侧的宽度（可以让表单内容排列整齐） -->
    <el-form label-width="80px" :model="changePwdQuery" :rules="changePwdRules" ref="changePwdRefForm">
      <!-- 旧密码 -->
      <el-form-item label="旧密码" prop="oldPwd">
        <el-input type="password" v-model.trim="changePwdQuery.oldPwd" />
      </el-form-item>

      <!-- 新密码 -->
      <el-form-item label="新密码" prop="newPwd">
        <el-input type="password" v-model.trim="changePwdQuery.newPwd" />
      </el-form-item>

      <!-- 确认新密码 -->
      <el-form-item label="确认密码" prop="confirmPwd">
        <el-input type="password" v-model.trim="changePwdQuery.confirmPwd" />
      </el-form-item>
    </el-form>

    <template #footer>
      <el-button type="primary" @click="changePwdSubmit()">提交</el-button>
      <el-button @click="changePwdClose()" >关闭</el-button>
    </template>
  </el-dialog>

</template>

<script>
import {doGet, doPost, doPut} from "../http/httpRequest.js";
  import {messageConfirm, messageTip, removeToken} from "../util/util.js";

  export default {
    // 定义组件名
    name: "DashboardView",

    data() {
      return {
        // 控制左侧菜单栏的左右折叠与展开，true是折叠，false是展开
        isCollapse: false,

        // 当前登录用户对象，初始值为空，页面渲染完成获取登录用户信息后赋值
        user: {
          // 菜单权限集合
          menuPermissionList: [
            {
              // 当前菜单的子菜单权限集合
              subMenuPermissionList:[]
            }
          ]
        },

        // 控制路由页面是否展示
        isRouterAlive: true,

        // 默认展开激活当前菜单的路由路径（当前访问的路径）
        currentRouterPath: '',

        // 我的资料对话框
        myInfoDialogVisible: false,

        // 修改密码对话框
        changePwdDialogVisible: false,

        // 修改密码参数对象
        changePwdQuery: { },

        // 修改密码表单验证规则
        changePwdRules: {
          // 旧密码
          oldPwd: [
            { required: true, message: '请输入旧密码', trigger: 'blur' },
            // 密码验证的正则
            { pattern: /^\d{6,12}$/, message: '密码为6-12位的数字', trigger: 'blur' },
            // validator：方法验证，绑定一个函数（判断旧密码是否正确）
            // 注意：函数不要加括号，element-plus框架会自动传入三个参数：rule规则、value值、callback回调
            { validator: this.checkOldPwd, trigger: 'blur' }
          ],
          // 新密码
          newPwd: [
            { required: true, message: '请输入新密码', trigger: 'blur' },
            // 密码验证的正则
            { pattern: /^\d{6,12}$/, message: '密码为6-12位的数字', trigger: 'blur' }
          ],
          // 确认密码
          confirmPwd: [
            { required: true, message: '请再次输入新密码', trigger: 'blur' },
            // 密码验证的正则
            { pattern: /^\d{6,12}$/, message: '密码为6-12位的数字', trigger: 'blur' },
            // validator：方法验证，绑定一个函数（判断和第一次输入的新密码是否一致）
            // 注意：函数不要加括号，element-plus框架会自动传入三个参数：rule规则、value值、callback回调
            { validator: this.checkConfirmPwd, trigger: 'blur' }
          ]
        }
      }
    },

    // 多级页面的数据穿透（provide提供/inject注入 组合）
    provide() {
      return {
        // 声明 reload 函数，要求使用箭头函数
        // 具体实现是通过路由组件的展示和隐藏，从而控制页面的再次加载，达到刷新的目的
        // 在需要进行刷新的页面中注入 DashboardView.vue 组件提供（provide）的 reload 函数，然后直接调用 this.reload() 来进行刷新
        reload: ()=> {
          this.isRouterAlive = false;
          // $nextTick()函数表示 vue 执行完渲染后会执行 this.nextTick()里面的 callback 函数
          // 当数据更新了，在dom中渲染后，自动执行该函数
          this.$nextTick(function () {
            this.isRouterAlive = true;
          })
        }
      }
    },

    // vue的钩子函数，渲染完成后自动执行
    mounted() {
      // 加载当前登录用户
      this.loadLoginUser();

      // 加载当前路由路径
      this.loadCurrentRouterPath();
    },

    methods: {
      // 回到系统首页
      home() {
        // 跳转路由
        this.$router.push("/dashboard")
      },

      // 左侧菜单栏的左右展开和折叠
      showMenu() {
        this.isCollapse = !this.isCollapse;
      },

      // 加载当前登录用户
      loadLoginUser() {
        doGet("/api/login/info", {}).then( (resp) => {
          // 给当前登录用户对象赋值
          this.user = resp.data.data;
        });
      },

      // 加载当前路由路径
      loadCurrentRouterPath() {
        // 获取当前访问的路由路径
        let path = this.$route.path;

        // 截取拼接前两级路由路径
        // 例如：'/dashboard/activity/add'  --->  ['', 'dashboard', 'activity', 'add']
        let pathArray = path.split('/');
        // 当路由路径截取后的数组长度大于3的时候才进行拼接，不大于3没必要拼接
        if (pathArray.length > 3) {
          path = "/" + pathArray[1] + "/" + pathArray[2];
        }

        // 给当前路由路径赋值
        this.currentRouterPath = path;
      },

      // 我的资料按钮
      myInfo() {
        // 弹出对话框
        this.myInfoDialogVisible = true;
      },

      // 修改密码按钮
      changePwd() {
        // 弹出对话框
        this.changePwdDialogVisible = true;
      },

      // 验证旧密码是否正确
      checkOldPwd(rule, value, callback) {
        // 使用FormData对象传参
        let formData = new FormData();
        formData.append("oldPwd", this.changePwdQuery.oldPwd);
        // 向后端发送请求验证旧密码是否正确
        doPost("/api/user/checkOldPwd", formData).then( (resp) => {
          if (resp.data.code === 200) {
            // 验证通过
            return callback();
          } else {
            // 验证未通过
            return callback(new Error("旧密码错误，请重新输入"));
          }
        })
      },

      // 验证新密码是否一致
      checkConfirmPwd(rule, value, callback) {
        // 验证新密码是否一致
        if (this.changePwdQuery.newPwd === value) {
          // 验证通过
          return callback();
        } else {
          // 给出提示信息
          return callback(new Error("两次密码不一致"));
        }
      },

      // 修改密码提交按钮
      changePwdSubmit() {
        // 验证表单规则
        this.$refs.changePwdRefForm.validate( (isValid) => {
          if (isValid) {
            // 使用FormData对象传参
            let formData = new FormData();
            // 只需要提交新密码即可，因为旧密码的合法性已经验证过了
            formData.append("newPwd", this.changePwdQuery.newPwd);
            // 验证通过，向后端发送请求
            doPut("/api/user/changePwd", formData).then( (resp) => {
              if (resp.data.code === 200) {
                messageTip("修改成功", "success");
                // 关闭修改密码的对话框
                this.changePwdDialogVisible = false;
                // 清除token
                removeToken();
                // 回到登录页面，重新登录
                this.$router.push("/");
              } else {
                messageTip("修改失败", "error");
              }
            })
          }
        })
      },

      // 修改密码关闭按钮
      changePwdClose() {
        // 清空修改密码参数
        this.changePwdQuery = { };

        // 关闭对话框
        this.changePwdDialogVisible = false;
      },

      // 退出登录
      logout() {
        doGet("/api/logout", {}).then( (resp) => {
          // 判断是否退出成功
          if (resp.data.code === 200) {
            // 删除sessionStorage和localStorage中存储的token
            removeToken();
            // 提示信息
            messageTip("退出成功", "success");
            // 跳转到登录页面
            window.location.href = "/";
          } else {
            // 提示信息
            messageConfirm("退出异常, 是否强制退出?").then(() => {  // 用户点击确认按钮触发then
              // 删除sessionStorage和localStorage中存储的token
              removeToken();
              // 跳转登录页面
              window.location.href = '/';
            }).catch(() => {    // 用户点击取消按钮触发catch
              // 消息提示框
              messageTip("退出失败", "warning");
            })
          }
        })
      }
    }
  }
</script>

<style scoped>

  /* 左侧 */
  .el-aside {
    background-color: black;
  }

  /* 右侧：上（头部） */
  .el-header {
    background-color: azure;
    height: 35px;         /* 高度 */
    line-height: 35px;    /* 行高和高度保持一致，上下居中 */
  }

  /* 右侧：下（底部） */
  .el-footer {
    background-color: aliceblue;
    height: 35px;         /* 高度 */
    line-height: 35px;    /* 行高，和高度保持一致，（上下居中） */
    text-align: center;   /* 文本左右居中 */
  }

  /* 右侧内容 */
  .rightContent {
    height: calc(100vh);  /* 右侧计算100%的屏幕高度，主要内容铺满屏幕，左侧自动变化 */
  }

  /* 左侧菜单栏标题按钮 */
  .menuTitle {
    color: #f9f9f9;
    height: 35px;               /* 高度和右侧上保持一致 */
    line-height: 35px;          /* 行高，和高度保持一致，（上下居中） */
    text-align: center;         /* 文本左右居中 */
    width: 100%;                /* 宽度100% */
    background-color: #1a1a1a;  /* 黑色背景色 */
    border: 0px;                /* 边框厚度设置为0px（紧贴周围的元素，没有缝隙） */
  }

  /* 右侧头部展开折叠图标 */
  .show {
    cursor: pointer;      /* 光标移动到图标上后，光标变成小手样式 */
  }

  /* 右侧头部下拉菜单 */
  .el-dropdown {
    float: right;         /* 往右侧漂移 */
    line-height: 35px;    /* 行高和右侧头部高度保持一致（上下居中） */
  }

  /* 我的资料 */
  .detail {
    height: 30px;
    width: 100%;
    background-color: #f6f7fb;    /* 背景色 */
    padding-left: 2px;            /* 左侧内边距 */
    border: 1px solid #e6e7eb;    /* 1px 边框宽度， solid 实线边框， #e6e7eb 边框颜色 */
    border-radius: 4px;           /* 边框角的弧度 */
  }

</style>

